package cn.sfrog.project.biz.applet.service.impl;

import cn.sfrog.common.constant.Constants;
import cn.sfrog.common.core.domain.ApiAjaxResult;
import cn.sfrog.common.core.domain.entity.SysUser;
import cn.sfrog.common.core.domain.model.LoginUser;
import cn.sfrog.common.core.redis.RedisCache;
import cn.sfrog.common.utils.DateUtils;
import cn.sfrog.framework.web.service.SysPermissionService;
import cn.sfrog.framework.web.service.TokenService;
import cn.sfrog.project.biz.admin.domain.BizUserAccount;
import cn.sfrog.project.biz.admin.mapper.BizUserAccountMapper;
import cn.sfrog.project.biz.admin.service.IBizUserInviteRecordService;
import cn.sfrog.project.biz.applet.config.WxPayConfig;
import cn.sfrog.project.biz.applet.entity.AccompanyVisitorEntity;
import cn.sfrog.project.biz.applet.entity.BizPrizeRaffleEntity;
import cn.sfrog.project.biz.applet.entity.BizUserRaffleEntity;
import cn.sfrog.project.biz.applet.entity.VO.AccompanyVisitorVo;
import cn.sfrog.project.biz.applet.entity.VO.AccompanyVo;
import cn.sfrog.project.biz.applet.mapper.AccompanyVisitorMapper;
import cn.sfrog.project.biz.applet.mapper.AppletUserMapper;
import cn.sfrog.project.biz.applet.service.AppletUserService;
import cn.sfrog.project.biz.applet.utils.WechatUtil;
import cn.sfrog.system.mapper.SysUserMapper;
import cn.sfrog.system.service.ISysUserService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author chen
 * @Date 2023-11-27 10:49
 * @title AppletUserServiceImpl
 * @description
 **/
@Slf4j
@Service
public class AppletUserServiceImpl implements AppletUserService {

    @Autowired
    WxPayConfig wxPayConfig;

    @Autowired
    private AppletUserMapper appletUserMapper;
    @Autowired
    private AccompanyVisitorMapper accompanyVisitorMapper;
    @Resource
    private SysPermissionService permissionService;
    @Autowired
    private BizUserAccountMapper bizUserAccountMapper;
    @Autowired
    private IBizUserInviteRecordService bizUserInviteRecordService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    ISysUserService userService;
    @Autowired
    private RedisCache redisCache;
    @Override
    public ApiAjaxResult loginAndRegister(String code, String phoneNumber,Long userId) {
        String key = Constants.APPLET_CACHE_PHONE_CODE_KEY + phoneNumber;
        Object cacheObject = redisCache.getCacheObject( key );
        if (!code.equals(cacheObject)){
            log.info("AppletUserServiceImpl:loginAndRegister-------验证码错误");
            return ApiAjaxResult.error("4001","验证码错误");
        }
        if (cacheObject == null){
            log.info("AppletUserServiceImpl:loginAndRegister-------验证码失效");
            return ApiAjaxResult.error("4002","验证码失效");
        }

        SysUser sysUser = getSysUser(phoneNumber,userId);
        sysUser.getToken();
        return ApiAjaxResult.success("200",sysUser);
    }

    @Override
    public ApiAjaxResult userRaffle() {
        List<BizPrizeRaffleEntity> allBizPrizeRaffle = appletUserMapper.getAllBizPrizeRaffle();
        int i = luckDraw(allBizPrizeRaffle);
        BizPrizeRaffleEntity bizPrizeRaffleEntity = allBizPrizeRaffle.get(i);
        if (i == -1){
            return ApiAjaxResult.success("抽奖池为空！无法抽奖，请于管理员联系！");
        }
        bizPrizeRaffleEntity.setRate(null);
        return ApiAjaxResult.success(bizPrizeRaffleEntity);
    }

    @Override
    public ApiAjaxResult bizPrizeRaffle() {
        List<BizPrizeRaffleEntity> allBizPrizeRaffle = appletUserMapper.getAllBizPrizeRaffle();
        allBizPrizeRaffle.stream().map((a)->{
            a.setRate(null);
            return a;
        }).collect(Collectors.toList());
        return  ApiAjaxResult.success(allBizPrizeRaffle);
    }

    @Override
    public ApiAjaxResult insertUserRaffle(BizUserRaffleEntity bizUserRaffleEntity) {
        BizPrizeRaffleEntity bizPrizeRaffleById = appletUserMapper.getBizPrizeRaffleById(bizUserRaffleEntity.getRaffleId());
        if (bizPrizeRaffleById == null){
            return ApiAjaxResult.error("无法查询到该奖品记录");
        }
        appletUserMapper.insertUserRaffle(bizUserRaffleEntity);
        return ApiAjaxResult.success();
    }

    @Override
    public ApiAjaxResult AuthorizedLogin(String phoneNumber,String loginCode) {
        SysUser sysUser = null;
        HashMap<String, String> openId = null;
        sysUser = getSysUser(phoneNumber,null);
        userMapper.updateUser(sysUser);
        return ApiAjaxResult.success(sysUser);
    }

    @Override
    public List<AccompanyVisitorEntity> visitorAccompany(String id) {
        List<AccompanyVisitorEntity> accompanyVisitorEntities = accompanyVisitorMapper.visitorAccompany(id);
        return accompanyVisitorEntities;
    }

    @Override
    public ApiAjaxResult insertVisitor(AccompanyVisitorVo accompanyVisitorVo) {
        AccompanyVisitorEntity visitorAccompany = accompanyVisitorMapper.getVisitorAccompany(accompanyVisitorVo);
        System.out.println(visitorAccompany);
        if(visitorAccompany == null){
            accompanyVisitorVo.setCreateTime(new Date());
            accompanyVisitorMapper.insertVisitor(accompanyVisitorVo);
            return ApiAjaxResult.success();
        }else{
            return ApiAjaxResult.error(2001,"该用户已存在，请重新再试");
        }
    }

    @Override
    public ApiAjaxResult changeVisitorAccompany(AccompanyVisitorVo accompanyVisitorVo) {
        int i = accompanyVisitorMapper.changeVisitorAccompany(accompanyVisitorVo);
        if (i>0){
            return ApiAjaxResult.success();
        }
        return null;
    }

    @Override
    public ApiAjaxResult deleteVisitorAccompany(String id) {
        int i = accompanyVisitorMapper.deleteVisitorAccompany(id);
        if (i>0){
            return ApiAjaxResult.success();
        }
        return null;
    }

    @Override
    public ApiAjaxResult getAccompanyList() {
        List<AccompanyVo> accompanyList = accompanyVisitorMapper.getAccompanyList();
        return ApiAjaxResult.success(accompanyList);
    }

    @Override
    public ApiAjaxResult updateOpenIdByPhoneNumber(String loginCode, String phoneNumber) {
        SysUser sysUser = null;
        String openid = "";
        HashMap<String, String> openId = new HashMap<>();
        sysUser = getSysUser(phoneNumber,null);
//        System.out.println(sysUser.getOpenId());
        openId = getOpenId(loginCode);
        System.out.println(openId.get("openid")+openId.get("state"));
        if (sysUser.getOpenId() == null){
            openid = openId.get("openid");
            //获取到openId
            sysUser.setOpenId(openid);
            userMapper.updateUser(sysUser);
        }
        if (openId.get("state") == "ok"){
            return ApiAjaxResult.success(openId);
        }else{
            return ApiAjaxResult.error("无法获取到用户的openId");
        }
    }

    /**
     * 抽奖功能
     * @param rates
     * @return -1   抽奖池为空，无法参与抽奖
     */
    private int luckDraw(List rates) {
        //抽奖  -1 抽奖池为空，无法参与抽奖
        if (CollectionUtils.isEmpty(rates)) {
            return -1;
        }
        //计算总概率，概率集合累加
        double totalRate = 0d;
        for (int i = 0; i < rates.size(); i++) {
            BizPrizeRaffleEntity o = (BizPrizeRaffleEntity) rates.get(i);
            System.out.println(o);
            Double aDouble = o.getRate();
            totalRate += aDouble;
        }
        // 每个奖品在总概率基础下的概率
        List sortRates = new ArrayList<>();
        double everyRate = 0d;
        for (int i = 0; i < rates.size(); i++) {
            BizPrizeRaffleEntity o = (BizPrizeRaffleEntity) rates.get(i);
            Double aDouble = o.getRate();
            everyRate += aDouble;
            sortRates.add(everyRate / totalRate);
        }
        // 根据区块值来获取抽取到的物品索引
        double nextDouble = Math.random();
        sortRates.add(nextDouble);
        Collections.sort(sortRates);
        return sortRates.indexOf(nextDouble);
    }

    //获取OpenId
    @Async
    HashMap<String, String> getOpenId(String loginCode){
        JSONObject sessionKeyOrOpenId = WechatUtil.getSessionKeyOrOpenId(loginCode,wxPayConfig.getAppid(), "7d53a592ec1f2a6a336acd7daed64987", "authorization_code");
        System.out.println("sessionKeyOrOpenId"+sessionKeyOrOpenId);
        HashMap<String,String> hashMap = new HashMap();
        //sessionKeyOrOpenId成功：{"unionid":"okXQX6en3Dt-UEWpG5aGsg4F1Oe4","openid":"oiWN569j2NwwaSjnR6BI_03PzYxg","session_key":"+74LAC7zYR868l+bJLn4XQ=="}
        //sessionKeyOrOpenId失败：{"errcode":40163,"errmsg":"code been used, rid: 6597c0d2-0af2c90b-0204b0c9"}
        if(sessionKeyOrOpenId != null){
            //请求成功，不管返回的是什么，总归是有参数的
            //获取 unionid
            Object union = sessionKeyOrOpenId.get("unionid");
            Object err = sessionKeyOrOpenId.get("errcode");
            if (union != null && String.valueOf(union).length() > 0){
                //正常情况 unionid必定是有的，请求失败的情况下 unionid不会存在
                //所以请求成功
                // sessionKey0rOpenId为：  {"unionid":"okXQX6en3Dt-UEWpG5aGsg4F1Oe4","openid":"oiWN569j2NwwaSjnR6BI_03PzYxg","session_key":"+74LAC7zYR868l+bJLn4XQ=="}
                //正常操作，取出需要的值
                String unionid = String.valueOf(union); //正常情况 unionid肯定有值
                String openid = String.valueOf(sessionKeyOrOpenId.get("openid"));//正常情况 openid肯定有值
                String session_key = String.valueOf(sessionKeyOrOpenId.get("session_key"));//正常情况 session_key肯定有值
                hashMap.put("state","ok");
                hashMap.put("unionid",unionid);
                hashMap.put("openid",openid);
                hashMap.put("sessionKey",session_key);
            }else if (err != null && String.valueOf(err).length() > 0){
                //请求失败
                //sessionKey0rOpenId对象为 {"errcode":40163,"errmsg":"code been used, rid: 6597c0d2-0af2c90b-0204b0c9"}
                //正常操作，取出需要的值
                String errcode = String.valueOf(err); //正常情况 errcode肯定有值
                String errmsg = String.valueOf(sessionKeyOrOpenId.get("errmsg"));//正常情况 errmsg肯定有值
                String rid = String.valueOf(sessionKeyOrOpenId.get("rid"));//正常情况 rid肯定有值
                hashMap.put("state","error");
                hashMap.put("errcode",errcode);
                hashMap.put("errmsg",errmsg);
                hashMap.put("rid",rid);
            }
        }else {
            hashMap.put("state","errorNull");
        }
        return hashMap;
    }
    //用户注册或者登录
    @Async
    SysUser getSysUser(String phoneNumber,Long userId){
        SysUser sysUser = null;
        sysUser = userMapper.selectAppUserByPhone(phoneNumber);
        if (sysUser == null){
            SysUser newUser = new SysUser();
            //  注册
            newUser.setUserName(phoneNumber);
            newUser.setNickName(phoneNumber);
            newUser.setPhonenumber(phoneNumber);
            newUser.setCreateBy("admin");
            userService.insertUser(newUser);
            sysUser = userMapper.selectAppUserByPhone(phoneNumber);
            //  创建用户账户信息
            BizUserAccount bizUserAccount = new BizUserAccount();
            bizUserAccount.setUserId(sysUser.getUserId());
            bizUserAccount.setCreateTime(DateUtils.getNowDate());
            bizUserAccount.setUpdateTime(DateUtils.getNowDate());
            bizUserAccount.setCreateBy("admin");
            bizUserAccount.setUpdateBy("admin");
            bizUserAccountMapper.insert(bizUserAccount);
            //  创建邀请记录
            //  获取陪依创始人
            if (userId == null){
                SysUser UserInfo = userMapper.selectAppUserByPhone("18662621080");
//                System.out.println("用户信息"+UserInfo);
                bizUserInviteRecordService.creatUserInviteRecord(UserInfo.getUserId(),sysUser.getUserId());
            }else{
                bizUserInviteRecordService.creatUserInviteRecord(userId,sysUser.getUserId());
            }
        }
        //  登录
        Set<String> perms = new HashSet<String>();
        //  给所有权限
        perms.add("*:*:*");
        LoginUser loginUser = new LoginUser(sysUser, perms);
        String token = tokenService.createToken(loginUser);
        sysUser.setToken(token);
        sysUser.setUserType(sysUser.getUserType());
        return sysUser;
    }
}
